#coding=utf-8

from tornado.web import RequestHandler
from tornado.log import access_log as logger
from tornado.gen import coroutine,Return

from .ViewMaker import BasicView, ChainView,OptionView,JsonView
from .error import CoreError


class MetaHandler(RequestHandler):
    methods = None

    @coroutine
    def get(self, *args, **kwargs):
        try:
            method_info = self.methods.get('get')
            if method_info is None:
                self.send_error(status_code=404, reason="not found")
                return
            call_func = method_info['func']
            filter_funcs = method_info['filters']
            request_obj = MeepoRequest(self)
            # 执行filter函数, 并获取处理结果
            for each_filter in filter_funcs:
                viewObj = each_filter(request_obj)
                if not isinstance(viewObj, BasicView):
                        self.send_error(status_code=500, reason="internal error")
                        return
                    # 如果是 chainView, 执行下一个filter
                if isinstance(viewObj, ChainView):
                    continue
                        # 遇到其它视图, 直接中断处理, 返回该视图
                viewObj.render(reqHandler=self)
                return

            try:
                viewObj = yield call_func(request_obj,*args,**kwargs)
            except CoreError as e:
                logger.error('%s:%s' % (e.__class__.__name__,e.message))
                if getattr(e,"can_out_put",None):
                    msg = e.message
                else:
                    msg = ""
                viewObj = JsonView({'code':'ERROR','msg':msg,'data':{}})
                viewObj.render(reqHandler=self)
                return

            if not isinstance(viewObj, BasicView):
                self.send_error(status_code=500, reason="internal error")
                return
            viewObj.render(reqHandler=self)
        except Exception as e:
            logger.exception(e)
            self.send_error(status_code=500, reason='internal error')

    @coroutine
    def post(self, *args, **kwargs):
        try:
            method_info = self.methods.get('post')
            if method_info is None:
                self.send_error(status_code=404, reason="not found")
                return
            call_func = method_info['func']
            filter_funcs = method_info['filters']
            request_obj = MeepoRequest(self)
            # 执行filter函数, 并获取处理结果
            for each_filter in filter_funcs:
                viewObj = each_filter(request_obj)
                if not isinstance(viewObj, BasicView):
                        self.send_error(status_code=500, reason="internal error")
                        return
                    # 如果是 chainView, 执行下一个filter
                if isinstance(viewObj, ChainView):
                    continue
                        # 遇到其它视图, 直接中断处理, 返回该视图
                viewObj.render(reqHandler=self)
                return
            try:
                viewObj = yield call_func(request_obj,*args,**kwargs)
            except CoreError as e:
                logger.error('%s:%s' % (e.__class__.__name__,e.message))
                if getattr(e,"can_out_put",None):
                    msg = e.message
                else:
                    msg = ""
                viewObj = JsonView({'code':'ERROR','msg':msg,'data':{}})
                viewObj.render(reqHandler=self)
                return

            if not isinstance(viewObj, BasicView):
                self.send_error(status_code=500, reason="internal error")
                return
            viewObj.render(reqHandler=self)
        except Exception as e:
            logger.exception(e)
            self.send_error(status_code=500, reason='internal error')

    def options(self, *args, **kwargs):
        viewObj = OptionView()
        viewObj.render(reqHandler=self)


class MeepoRequest:
    """ 对 RequestHandler 的再封装
        来控制 request 只能提取 request 信息, 不能做response动作
        response 动作只能交给封装好的 view 对象来统一处理

        标准化 接口开发流程, 降低接口开发繁复度
    """

    def __init__(self, httpReq):
        if not isinstance( httpReq, RequestHandler ):
            raise Exception

        self.__httpReq = httpReq
        self.session = None
        self.user= None

    def get_argument(self, name,default=None):
        return self.__httpReq.get_argument( name=name, default=default )

    def get_query_string(self):
        return self.__httpReq.request.query

    def get_uri(self):
        return self.__httpReq.request.path

    def get_header(self):
        return self.__httpReq.request.headers

    def get_body(self):
        return self.__httpReq.request.body

    def get_remote_ip(self):
        return self.__httpReq.request.remote_ip

    def get_host(self):
        return self.__httpReq.request.host

    def get_full_url(self):
        return self.__httpReq.request.full_url

    def get_cookie(self, name):
        return self.__httpReq.get_cookie(name)

    def set_cookie(self, name, value, exprie):
        return self.__httpReq.set_cookie(name=name, value=value, expires=exprie)

    def set_session(self, session):
        self.session = session

    def get_session(self):
        return self.session

    def set_user(self,user_id):
        self.user = int(user_id)

    def get_user(self):
        return self.user

    def get_file(self,name,default):
        return self.__httpReq.request.files.get(name=name,default=default)